package btc.view.action;

import btc.backend.clasificador.ClasificadorDePallet;
import btc.backend.clasificador.ClasificadorDePalletPorMuestras;
import btc.backend.clasificador.ClasificadorDePalletPorMuestrasYUmbral;
import btc.backend.clasificador.ClasificadorPalletPorExtension;
import btc.backend.generator.Dimension;
import btc.backend.generator.GeneradorDePallet;
import btc.backend.servicios.MaquinaAppl;
import btc.backend.servicios.PalletAppl;
import btc.model.ClasificacionPallet;
import btc.model.Maquina;
import btc.model.Pallet;
import btc.transport.PalletTO;
import com.opensymphony.xwork2.ActionSupport;
import org.hamcrest.core.Is;

import java.text.SimpleDateFormat;
import java.util.*;

import static ch.lambdaj.Lambda.*;


public class PalletAction extends ActionSupport {


    private static String CLASIFICACION_MUESTRAS = "Pallet por muestras";
    private static String CLASIFICACION_MUESTRASYUMBRAL = "Pallet por muestras y umbral";
    private static String CLASIFICACION_EXTENSION = "Pallet por extensión";

    private Map<String, Object> resultadosJSON = new HashMap<String, Object>();

    private List<Maquina> maquinas;
    private int maquinaSeleccionada;
    private int cantidad;
    private Dimension dimension;

    private int muestras;
    private float umbralPrimera;
    private float umbralSegunda;

    private Map<String, ClasificadorDePallet> clasificadores = buildClasificadores();

    private Map<String, ClasificadorDePallet> buildClasificadores() {
        Map<String, ClasificadorDePallet> clasificadorDePalletMap = new HashMap<String, ClasificadorDePallet>();
        clasificadorDePalletMap.put(CLASIFICACION_EXTENSION, new ClasificadorPalletPorExtension());
        clasificadorDePalletMap.put(CLASIFICACION_MUESTRAS, new ClasificadorDePalletPorMuestras());
        clasificadorDePalletMap.put(CLASIFICACION_MUESTRASYUMBRAL, new ClasificadorDePalletPorMuestrasYUmbral());
        return clasificadorDePalletMap;
    }

    private String clasificacion;

    private List<String> keys;


    public String generate() {
        GeneradorDePallet generadorDePallet = new GeneradorDePallet();
        int newPalletId = generadorDePallet.generar(this.cantidad, dimension, this.getMaquinaSeleccionada());
        PalletAppl palletAppl = new PalletAppl();
        Pallet newPallet = palletAppl.obtenerPalletPorId(newPalletId);
        this.clasificadores.get(this.getClasificacion()).clasificar(newPallet, this.getMuestras(), this.getUmbralPrimera(), this.getUmbralSegunda());
        return SUCCESS;
    }

    public String prepareGenerate() {
        this.keys = Arrays.asList(CLASIFICACION_EXTENSION, CLASIFICACION_MUESTRAS, CLASIFICACION_MUESTRASYUMBRAL);
        this.maquinas = MaquinaAppl.obtenerMaquinas();
        return SUCCESS;
    }

    private Set<String> generarAlertas(List<Pallet> pallets) {
        Set<String> maquinasDefectuosas = new HashSet<String>();
        for (Pallet pallet : pallets) {
            if (ClasificacionPallet.INSERVIBLE.equals(pallet.getClasificacionPallet())) {
                maquinasDefectuosas.add(filter(having(on(Maquina.class).getId(), Is.is(pallet.getIdMaquina())), this.maquinas).get(0).getDescripcion());
            }
        }
        return maquinasDefectuosas;
    }

    public String list() {
        this.maquinas = MaquinaAppl.obtenerMaquinas();
        PalletAppl palletAppl = new PalletAppl();
        Collection<Pallet> pallets = palletAppl.obtenerPallets();
        this.resultadosJSON.put("pallets", convertPalletsToTO(pallets));
        Set<String> maquinasDefectuosas = generarAlertas(new ArrayList<Pallet>(pallets));
        if (maquinasDefectuosas != null && !maquinasDefectuosas.isEmpty()) {
            this.resultadosJSON.put("alerts", maquinasDefectuosas);
        }
        return SUCCESS;
    }

    public String stats() {
        Map<String, Object> stats = new HashMap<String, Object>();
        PalletAppl palletAppl = new PalletAppl();
        stats.put("palletXClasificacion", palletAppl.obtenerPalletsPorClasificacion());
        stats.put("palletXMaquina", palletAppl.obtenerPalletPorMaquina());
        this.resultadosJSON.put("stats", stats);
        return SUCCESS;
    }
       
    private Collection<PalletTO> convertPalletsToTO(Collection<Pallet> pallets) {
        Collection<PalletTO> tos = new ArrayList<PalletTO>();
        for (Pallet pallet : pallets) {
            tos.add(convertToDTO(pallet));
        }
        return tos;
    }

    //esto de los DTOs es para tener lo que quiera en la vista, no por giladas (?) de diseño
    private PalletTO convertToDTO(Pallet pallet) {
        java.text.SimpleDateFormat sdf= new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        String fecha = sdf.format(pallet.getFechaProceso());
        String nombreMaquina = filter(having(on(Maquina.class).getId(), Is.is(pallet.getIdMaquina())), this.maquinas).get(0).getDescripcion();
        return new PalletTO(pallet.getId(), pallet.getClasificacionPallet(),
                pallet.getCantidadDeBloquesDefectuosos(), nombreMaquina, fecha);
    }

    public Map<String, Object> getResultadosJSON() {
        return resultadosJSON;
    }

    public void setResultadosJSON(Map<String, Object> resultadosJSON) {
        this.resultadosJSON = resultadosJSON;
    }

    public List<Maquina> getMaquinas() {
        return maquinas;
    }

    public void setMaquinas(List<Maquina> maquinas) {
        this.maquinas = maquinas;
    }

    public int getMaquinaSeleccionada() {
        return maquinaSeleccionada;
    }

    public void setMaquinaSeleccionada(int maquinaSeleccionada) {
        this.maquinaSeleccionada = maquinaSeleccionada;
    }

    public int getCantidad() {
        return cantidad;
    }

    public void setCantidad(int cantidad) {
        this.cantidad = cantidad;
    }

    public Dimension getDimension() {
        return dimension;
    }

    public void setDimension(Dimension dimension) {
        this.dimension = dimension;
    }

    public String getClasificacion() {
        return clasificacion;
    }

    public void setClasificacion(String clasificacion) {
        this.clasificacion = clasificacion;
    }

    public List<String> getKeys() {
        return keys;
    }

    public void setKeys(List<String> keys) {
        this.keys = keys;
    }

    public int getMuestras() {
        return muestras;
    }

    public void setMuestras(int muestras) {
        this.muestras = muestras;
    }

    public float getUmbralPrimera() {
        return umbralPrimera;
    }

    public void setUmbralPrimera(float umbralPrimera) {
        this.umbralPrimera = umbralPrimera;
    }

    public float getUmbralSegunda() {
        return umbralSegunda;
    }

    public void setUmbralSegunda(float umbralSegunda) {
        this.umbralSegunda = umbralSegunda;
    }
}
